package cn.jdemo.unsafe.memory;

import sun.misc.Unsafe;

/**
 * 申请的内存地址,不归JVM管理
 *
 * @see Unsafe#allocateMemory(long)
 *  (1)向本地系统申请一块内存地址;(2)返回内存地址的起始地址(3)内存的使用脱离jvm，gc无法管理,故要要手动释放内存，避免内存溢出;
 *
 * @see Unsafe#freeMemory(long)
 *  (1) 释放给定内存地址的内存，若在使用改地址，JVM崩溃报错
 * 
 * @see Unsafe#reallocateMemory(long address, long size)
 *  (1) 释放给定内存地址所使用的内存;(2)重新申请给定大小的内存
 *
 * putXXX(long addr,val) 第一个参数是申请的内存地址，第二个参数是要赋的值
 * @see Unsafe#putAddress(long addr, long addr)
 * @see Unsafe#putByte(long addr, byte)
 * @see Unsafe#putChar(long addr, char)
 * @see Unsafe#putLong(long addr, long)
 * @see Unsafe#putInt(long addr, int)
 * @see Unsafe#putShort(long addr, short)
 * @see Unsafe#putDouble(long addr, double)
 * @see Unsafe#putFloat(long addr, float)
 * @see Unsafe#putBoolean(Object, long, boolean) // boolean型，没有基于申请的内存，存储数据
 *
 *
 * @see Unsafe#getByte(long addr) 基于内存地址
 * @see Unsafe#getByte(Object, long offset) 基于对象/类变量 + 内存偏移量
 *
 *
 * @date 2021/1/15
 */
public class Demo01 {
    public static void main(String[] args) {
        // test01();
        // test02();
        test03();
    }

    /**
     * 输出内容:
     * Exception in thread "main" java.lang.OutOfMemoryError
     */
    public static void test01() {
        Unsafe theUnasfe = cn.jdemo.unsafe.theUnsafe.AllInOne.getTheUnasfe();
        long l = theUnasfe.allocateMemory(Long.MAX_VALUE);
        System.out.println(l);
    }

    /**
     * @see Unsafe#allocateMemory(long) 返回申请内存的起始地址
     */
    public static void test02() {
        Unsafe theUnasfe = cn.jdemo.unsafe.theUnsafe.AllInOne.getTheUnasfe();
        long addr = theUnasfe.allocateMemory(1024);
        System.out.println(addr);//337676144
    }

    /**
     * @see Unsafe#freeMemory(long addr) 释放给定内存地址的内存
     *
     * 输出内容:
     * 88
     */
    public static void test03() {
        // 获取内存地址，并分配byte字段a
        Unsafe theUnasfe = cn.jdemo.unsafe.theUnsafe.AllInOne.getTheUnasfe();
        long addr = theUnasfe.allocateMemory(1024);
        theUnasfe.putByte(addr, (byte) 'a');

        // 释放内存地址
        theUnasfe.freeMemory(addr);

        // 仍然可以基于改地址获取数据
        byte aByte = theUnasfe.getByte(addr);
        System.out.println(aByte);// 88
    }

    /**
     * @see Unsafe#freeMemory(long addr) 释放给定内存地址的内存
     *
     * 输出内容:(JVM报错)
     * A fatal error has been detected by the Java Runtime Environment:
     * EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000779a382d, pid=8868, tid=0x0000000000003a20
     */
    public static void test04() {
        // 获取内存地址，并分配byte字段a
        Unsafe theUnasfe = cn.jdemo.unsafe.theUnsafe.AllInOne.getTheUnasfe();
        long addr = theUnasfe.allocateMemory(1024);
        theUnasfe.putByte(addr, (byte) 'a');

        // 释放内存地址,并分配该地址int字段1==》JVM崩溃报错
        theUnasfe.freeMemory(addr);
        theUnasfe.putInt(addr, 1);

        /*byte aByte = theUnasfe.getByte(addr);
        System.out.println(aByte);// 88*/
    }


}
